package com.yc.framework.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class RabbitMQConfig {

    @Value("${spring.rabbitmq.host}")
    private String host;

    @Value("${spring.rabbitmq.port}")
    private int port;

    @Value("${spring.rabbitmq.username}")
    private String username;

    @Value("${spring.rabbitmq.password}")
    private String password;

    @Value("${spring.rabbitmq.virtual-host}")
    private String virtualHost;

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host);
        connectionFactory.setPort(port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        // 开启发布确认
        connectionFactory.setPublisherConfirms(true);
        // 开启发布返回
        connectionFactory.setPublisherReturns(true);
        return connectionFactory;
    }

    // 配置消息转换器为 JSON 格式
    @Bean
    public Jackson2JsonMessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    // 配置 RabbitTemplate 并注入消息转换器
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory,
                                         Jackson2JsonMessageConverter messageConverter) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(messageConverter);
        // 开启 Mandatory，确保消息无法路由时返回（用于处理失败消息）
        template.setMandatory(true);
        return template;
    }

    // 定义邮件验证码队列
    @Bean
    public Queue emailCaptchaQueue() {
        Map<String, Object> args = new HashMap<>();
        // 设置死信交换机
        args.put("x-dead-letter-exchange", "email.captcha.dlx");
        // 设置死信路由键
        args.put("x-dead-letter-routing-key", "email.captcha.dlrk");
        // 设置消息过期时间（10分钟）
        args.put("x-message-ttl", 600000);
        return new Queue("email.captcha.queue", true, false, false, args);
    }

    // 定义邮件验证码交换机
    @Bean
    public DirectExchange emailCaptchaExchange() {
        return new DirectExchange("email.captcha.exchange", true, false);
    }

    // 定义邮件验证码绑定关系
    @Bean
    public Binding emailCaptchaBinding() {
        return BindingBuilder.bind(emailCaptchaQueue())
                .to(emailCaptchaExchange())
                .with("email.captcha.routingKey");
    }

    // 定义邮件验证码死信队列
    @Bean
    public Queue emailCaptchaDLQueue() {
        return new Queue("email.captcha.dl.queue", true);
    }

    // 定义邮件验证码死信交换机
    @Bean
    public DirectExchange emailCaptchaDLExchange() {
        return new DirectExchange("email.captcha.dlx", true, false);
    }

    // 定义邮件验证码死信绑定关系
    @Bean
    public Binding emailCaptchaDLBinding() {
        return BindingBuilder.bind(emailCaptchaDLQueue())
                .to(emailCaptchaDLExchange())
                .with("email.captcha.dlrk");
    }

    // 定义队列（例如：文档上传、文档预览等场景可能会使用到多个队列，这里以文档队列为例）
    @Bean
    public Queue documentQueue() {
        // true 表示持久化队列
        return new Queue("document.queue", true);
    }

    // 定义交换机
    @Bean
    public DirectExchange documentExchange() {
        return new DirectExchange("document.exchange");
    }

    // 定义绑定关系，将队列和交换机通过路由键绑定
    @Bean
    public Binding documentBinding(Queue documentQueue, DirectExchange documentExchange) {
        return BindingBuilder.bind(documentQueue)
                .to(documentExchange)
                .with("document.routingKey");
    }

}
